
package com.kugou.game.sdk.observers;

import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;

import java.util.HashSet;

/**
 * 描述:变动监听类
 * 
 * @author ljc
 * @since 2014-3-25 下午3:05:22
 */
public abstract class BaseContentObserver extends ContentObserver {

    private static String TAG = BaseContentObserver.class.getSimpleName();

    public static final int CONTACT_DB_OBSERVER = 1;

    public static final int GROUP_DB_OBSERVER = 2;

    public static final int MESSAGE_DB_OBSERVER = 3;

    public static final int CALLS_DB_OBSERVER = 4;

    protected boolean mIsClose = false;// 是否关闭数据库监听

    protected final boolean DEBUG = false;

    protected Message mMessage;

    protected final int MESSAGE_WHAT = 1;

    protected final int MESSAGE_NOTIFY = 2;

    protected Context mContext;

    /**
     * 数据库变动监听接口
     * 
     * @author Jack
     */
    public interface OnContentChangeListener {

        /**
         * 当数据库变动是调用
         */
        public void onContentChange(int whoObserver);
    }

    protected final HashSet<OnContentChangeListener> mListeners = new HashSet<OnContentChangeListener>();

    private long DELAY_TIME = 500;// 数据库变动最大间隔时间

    public BaseContentObserver(Context context) {
        super(new Handler());
        mContext = context;
    }

    public abstract void registerContentObserver();

    public void setObserverDelayed(long delayed) {
        DELAY_TIME = delayed;
    }

    public void addOnContentChangeListener(OnContentChangeListener listener) {
        synchronized (mListeners) {
            if (!mListeners.contains(listener)) {
                mListeners.add(listener);
            }
        }
    }

    public void removeOnContentChangeListener(OnContentChangeListener listener) {
        synchronized (mListeners) {
            mListeners.remove(listener);
        }
    }

    /**
     * 关闭监听
     */
    public void closeObserver() {
        mIsClose = true;
    }

    /**
     * 打开监听
     */
    public void openObserver() {
        mIsClose = false;
    }

    /**
     * 延时打开监听
     * 
     * @param delayed 延时
     */
    public void openObserver(long delayed) {
        mHandler.postDelayed(new Runnable() {

            public void run() {
                mIsClose = false;
            }
        }, delayed);

    }

    /**
     * 通知监听的人们，你们该去刷新数据了
     */
    public void notifyContentChange() {
        mMessage = mHandler.obtainMessage(MESSAGE_NOTIFY);
        mMessage.sendToTarget();
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        if (mIsClose) {
            return;
        }
        if (DEBUG)
            if (mMessage != null && SystemClock.uptimeMillis() - mMessage.getWhen() < DELAY_TIME) {
                mHandler.removeMessages(MESSAGE_WHAT);
            }
        mMessage = mHandler.obtainMessage(MESSAGE_WHAT);
        mHandler.sendMessageDelayed(mMessage, DELAY_TIME);
        onEveryChange();

    }

    /**
     * call by every time changed
     */
    protected void onEveryChange() {
        // TODO Auto-generated method stub

    }

    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MESSAGE_WHAT:
                    if (isCallBack())
                        callBackContentChange();
                    break;
                case MESSAGE_NOTIFY:
                    callBackContentChange();
            }
        }
    };

    @SuppressWarnings("unchecked")
    private void callBackContentChange() {
        HashSet<OnContentChangeListener> iterator;
        synchronized (mListeners) {
            iterator = (HashSet<OnContentChangeListener>) mListeners.clone();
        }
        for (OnContentChangeListener l : iterator) {
            l.onContentChange(getDbObserver());
        }
    }

    /**
     * @return {@link #CONTACT_DB_CHANGED}, {@link #GROUP_DB_CHANGED},
     *         {@link #MESSAGE_DB_CHANGED}
     */
    protected abstract int getDbObserver();

    protected boolean isCallBack() {
        return true;
    }
}
